package com.xuqi.W3;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * This class handles raw HTTP data received from server. Here, "raw data"
 * means data before decompression but after "chunked-encoding" decode being
 * applied.
 * 
 * The main reason why introducing this class is to count how many raw bytes
 * of response body we read from the socket.
 * 
 * IMPORTANT: On Android-2.3 (or maybe higher version), it REQUIRES you to
 * set request header "Accept-Encoding" to make it works correctly.
 * 
 * @author $Author: kuang $
 */
public class W3HttpRawInputStream extends InputStream {

	private int			m_iReadBytes		= 0;
	private int			m_iMarkPos			= 0;
	private InputStream m_cExtInputStream	= null;

	/**
	 * Constructor
	 * 
	 * @param rawStream		: "InputStream" returned by "HttpURLConnection.getInputStream"
	 * @throws IOException	: 
	 */
	public W3HttpRawInputStream(InputStream rawStream) throws IOException {
		super();
		m_cExtInputStream = new BufferedInputStream(rawStream, 1024 * 8);
	}

	/**
	 * Get how many raw bytes we have read (before decompression) from socket for
	 * response body.
	 */
	public int getReadBytes() {
		return m_iReadBytes;
	}

	@Override
	public int available() throws IOException {
		return m_cExtInputStream.available();
	}

	@Override
	public void close() throws IOException {
		m_cExtInputStream.close();
	}

	@Override
	public void mark(int pos) {
		m_cExtInputStream.mark(pos);
		if ( markSupported() ) {
			m_iMarkPos = m_iReadBytes;
		}
	}

	@Override
	public boolean markSupported() {
		return m_cExtInputStream.markSupported();
	}

	@Override
	public int read(byte[] b, int offset, int length) throws IOException {
		int iLen = m_cExtInputStream.read(b, offset, length);
		if ( -1 != iLen ) {
			m_iReadBytes += iLen;
		}
		return iLen;
	}
	
	@Override
	public int read(byte[] b) throws IOException {
		int iLen = m_cExtInputStream.read(b);
		if ( -1 != iLen ) {
			m_iReadBytes += iLen;
		}
		return iLen;
	}

	@Override
	public int read() throws IOException {
		int chr = m_cExtInputStream.read();
		++m_iReadBytes;
		return chr;
	}
	
	@Override
	public void reset() throws IOException {
		synchronized(m_cExtInputStream) {
			m_cExtInputStream.reset();
			if ( markSupported() ) {
				m_iReadBytes = m_iMarkPos;
			}
		}
	}

	@Override
	public long skip(long n) throws IOException {
		long lCount = m_cExtInputStream.skip(n);
		m_iReadBytes += lCount;

		return lCount;
	}

}
